package com.hontech.bread.ui.view

import android.content.Context
import android.media.MediaPlayer
import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.View
import android.widget.FrameLayout
import android.widget.ImageView
import android.widget.VideoView
import com.hontech.bread.R
import com.hontech.bread.store.StoreAdvCfg
import com.hontech.bread.store.setImageWithFile
import com.hontech.bread.utils.AdvManager
import com.hontech.bread.utils.AdvNotFoundException
import com.hontech.bread.utils.log
import com.hontech.bread.utils.runOnUiCatchAny
import com.hontech.bread.utils.stringById
import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.TimeoutCancellationException
import kotlinx.coroutines.delay
import kotlinx.coroutines.withTimeout
import java.io.File

class PlayPauseException : Exception("${stringById(R.string.t1733460848_452)}")
class PlayError(msg: String) : Exception(msg)

class CustomVideoView(context: Context, attrs: AttributeSet) : VideoView(context, attrs),
    MediaPlayer.OnCompletionListener, MediaPlayer.OnErrorListener {
    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        val width = getDefaultSize(0, widthMeasureSpec)
        val height = getDefaultSize(0, heightMeasureSpec)
        setMeasuredDimension(width, height)
    }

    private var playPromise: CompletableDeferred<Unit>? = null

    init {
        setOnCompletionListener(this)
        setOnErrorListener(this)
    }

    override fun onError(mp: MediaPlayer?, what: Int, extra: Int): Boolean {
        super.pause()
        stopPlayback()
        val promise = playPromise
        playPromise = null
        promise?.completeExceptionally(PlayError("${stringById(R.string.t1733460848_453)} $what $extra"))
        return true
    }

    override fun onCompletion(mp: MediaPlayer?) {
        val promise = playPromise
        playPromise = null
        promise?.complete(Unit)
    }

    override fun pause() {
        super.pause()
        val promise = playPromise
        playPromise = null
        promise?.completeExceptionally(PlayPauseException())
    }

    suspend fun play(path: String) {
        val promise = CompletableDeferred<Unit>()
        playPromise = promise
        setVideoPath(path)
        start()
        promise.await()
    }
}

class MediaPlayer(context: Context, attrs: AttributeSet) : FrameLayout(context, attrs) {

    private val videoView: CustomVideoView
    private val imageView: ImageView
    private val position: Int
    private val imagePlayer: ImagePlayer

    init {
        val view = LayoutInflater.from(context).inflate(R.layout.view_media_player, this)
        videoView = view.findViewById(R.id.id_mp_cvv)
        imageView = view.findViewById(R.id.id_mp_img)
        imagePlayer = ImagePlayer(imageView)
        val attr = context.obtainStyledAttributes(attrs, R.styleable.MediaPlayer)
        position = attr.getInteger(R.styleable.MediaPlayer_mp_position, 0)

        attr.recycle()

        log("${stringById(R.string.t1733460848_454)}:$position")
    }

    private var stopFlag = true

    fun resume() {
        if (stopFlag) {
            stopFlag = false
            runOnUiCatchAny { playStart() }
        }
    }

    fun pause() {
        if (!stopFlag) {
            stopFlag = true
            videoView.pause()
            imagePlayer.pause()
        }
    }

    private suspend fun playStart() {
        while (true) {
            val adv = AdvManager.playNext(position)

            try {
                if (adv.isVideo()) {
                    playVideo(adv)
                } else if (adv.isImage()) {
                    playImage(adv)
                } else {
                    throw PlayError(stringById(R.string.t1733460848_455))
                }
            } catch (e: PlayError) {
                e.printStackTrace()

                delay(10 * 1000)
            } catch (e: AdvNotFoundException) {
                e.printStackTrace()

                delay(60 * 1000)
            }
        }
    }

    private suspend fun playVideo(adv: StoreAdvCfg) {
        videoView.visibility = View.VISIBLE
        imageView.visibility = View.INVISIBLE
        videoView.play(AdvManager.advPath(adv.advId))
    }

    private suspend fun playImage(adv: StoreAdvCfg) {
        videoView.visibility = View.INVISIBLE
        imageView.visibility = View.VISIBLE
        imagePlayer.play(AdvManager.advPath(adv.advId), adv.duration * 1000L)
    }
}

private class ImagePlayer(val imageView: ImageView) {

    private var playPromise: CompletableDeferred<Unit>? = null

    suspend fun play(path: String, duration: Long) {
        val promise = CompletableDeferred<Unit>()
        playPromise = promise
        imageView.setImageWithFile(File(path))
        try {
            withTimeout(duration) { promise.await() }
        } catch (e: TimeoutCancellationException) {
            return
        }
    }

    fun pause() {
        val promise = playPromise
        playPromise = null
        promise?.completeExceptionally(PlayPauseException())
    }
}













